var gamejs = require("gamejs");
var sounds = require("js/soundManager");
/**
 * Creates a ScenesDirector object. It could update and draw a scene.
 * It also stores a stack of scenes.
 *
 * @param {gamejs.Surface} surface The Surface object where to draw the scene.
 *
 * @constructor
 */
var ScenesDirector = exports.ScenesDirector = function(surface) {
	if(!(surface instanceof gamejs.Surface)) {
		throw new TypeError("this is not a surface object");
	}
	else {
		this.mainSurface = surface;
		this.scenesStack = [];
		this.onAir = false;
		// Creates a soundManager
		this.soundManager = new sounds.SoundManager();
	}
};

/**
 * Returns the Surface object where the game is drawn.
 *
 * @return {gamejs.Surface} The Surface object where the game is drawn.
 */
ScenesDirector.prototype.getSurface = function() {
	return this.mainSurface;
};

/**
 * Returns the soundManager object of the game.
 *
 * @return {soundManager} The soundManager object of the game.
 */
ScenesDirector.prototype.getSoundManager = function() {
	return this.soundManager;
};

/**
 * Process the active scene, calling its update and draw methods.
 *
 * @param {number} msDuration The time past from the last call, in ms.
 */
ScenesDirector.prototype.processScene = function(msDuration) {
	if(this.onAir) {
		this.getActiveScene().update(msDuration);
		this.getActiveScene().draw();
	}
};

/**
 * Sets the given scene as the active scene, than sets onAir to true.
 *
 * @param {Object} startScene The scene object to set as the active scene,
 * needs an update and a draw method.
 * @throws {TypeError} If startScene hasn't an update and a draw method.
 */
ScenesDirector.prototype.start = function(startScene) {
	this.changeScene(startScene);
	this.onAir = true;
};

/**
 * Removes all the scenes in stack and sets the given scene as the active scene.
 *
 * @param {Object} newScene The scene object to set as the active scene,
 * needs an update and a draw method.
 * @throws {TypeError} If newScene hasn't an update and a draw method.
 */
ScenesDirector.prototype.changeScene = function(newScene) {
	this.scenesStack = [];
	this.pushScene(newScene);
};

/**
 * Pushes the given scene in the scenes stack, making it the active scene.
 *
 * @param {Object} scene The scene object to set as the active scene,
 * needs an update and a draw method.
 * @throws {TypeError} If scene hasn't an update and a draw method.
 */
ScenesDirector.prototype.pushScene = function(scene) {
	if(scene.update && scene.draw) {
		this.scenesStack.push(scene);
		document.getElementsByTagName("body")[0].style.cursor = "default";
	}
	else {
		throw new TypeError("scene isn't a valid Scene object");
	}
	
	//update map background if it has to change
	if(this.getActiveScene().setActive){
		this.getActiveScene().setActive();
	}
};

/**
 * Removes the active scenes from the stack, than returns it.
 *
 * @return {Object} A scene object, it has an update and a draw method.
 */
ScenesDirector.prototype.popScene = function() {
	return this.scenesStack.pop();
};

/**
 * Returns the second scene in the stack.
 *
 * @return {Object} A scene object, it has an update and a draw method.
 */
ScenesDirector.prototype.getPreviousScene = function() {
	return this.scenesStack[this.scenesStack.length - 2];
};

/**
 * Returns the active scene (the first scene in the stack).
 *
 * @return {Object} The active scene object, it has an update and a draw method.
 */
ScenesDirector.prototype.getActiveScene = function() {
	return this.scenesStack[this.scenesStack.length - 1];
};